class HeapOperator {
    //上浮
    static upAdjust(arr = []) {
        let childIndex = arr.length - 1;
        let parentIndex = Math.floor((childIndex - 1) / 2); // (10 - 1) / 2 => 4
        let temp = arr[childIndex]; // 保存插入的叶子节点值，用于最后的赋值
        // 当 childIndex === 0 => root
        while (childIndex > 0 && temp < arr[parentIndex]) {
            arr[childIndex] = arr[parentIndex];
            childIndex = parentIndex;
            parentIndex = Math.floor((parentIndex - 1) / 2); // (2 - 1) / 2 => 0
        }
        arr[childIndex] = temp;
    }
    /**
     * 下沉
     * @param {*} arr 
     * @param {*} parentIndex 要下沉的父节点
     * @param {*} length 
     */
    static downAdjust(arr = [], parentIndex, length) {
        let temp = arr[parentIndex]; // 保存父节点的值，用于最后的赋值
        let childIndex = 2 * parentIndex + 1;
        while (childIndex < length) { // 超过范围退出
            // 如果有右孩子，且右孩子小于左孩子，则定位到右孩子
            if ((childIndex + 1) < length && arr[childIndex + 1] < arr[childIndex]) {
                childIndex++;
            }
            // 如果父节点小于任何一个孩子的值，直接跳出（上一步已经确保childIndex指向最小)
            if (temp <= arr[childIndex]) break;
            arr[parentIndex] = arr[childIndex];
            parentIndex = childIndex;
            childIndex = 2 * childIndex + 1;
        }
        arr[parentIndex] = temp;
    }
    // 构建堆
    static buildHeap(arr = []) {
        // 从最后一个非叶子节点开始，依次下沉调整
        for (let i = Math.floor((arr.length - 2) / 2); i >= 0; i--) {
            HeapOperator.downAdjust(arr, i, arr.length);
        }
    }
}

let arr = [1, 3, 2, 6, 5, 7, 8, 9, 10, 0]
HeapOperator.upAdjust(arr);
console.log(arr);

arr = [7, 1, 3, 10, 5, 2, 8, 9, 6];
HeapOperator.buildHeap(arr);
console.log(arr);